package com.game.manager
{
    import base.BaseAnimation;
    
    import com.dusk.game.Logger;
    import com.dusk.util.McUtil;
    import com.dusk.util.ResUtil;
    import com.dusk.util.UtilBase;
    import com.game.view.IAnimation;
    import com.game.view.display.AnimationClip;
    import com.game.view.display.BitmapMovieClip;
    import com.game.view.display.TextureGroup;
    
    import flash.display.MovieClip;
    
    import flash.utils.Dictionary;
    
    public class AnimationManager
    {
        private static var _cacheDict:Dictionary = new Dictionary();
        private static var _cacheGenerateQueue:Array = [];
        private static var _cacheSizeLimit:int = 100;
        private static var _limitCacheSize:Boolean = false;
        
        public static const ANIMATE_TYPE_BITMAP:int = 0;
        
        public static const ANIMATE_TYPE_MOVIE_CLIP:int = 1;
        
        private static function transformKey(name:String, info:Object, action:String = "default"):String
        {
            //todo
            //后期性能优化可能尝试把key改为一个hash值
            var key:String = name + UtilBase.getObjectID(info) + action;
            return key;
        }
        
        /**
         * 获取单独的、可渲染的动画（需要参数）
         * @param name 资源名称
         * @param info 目前没有用处
         * @param animateType 动画种类
         * @param smoothing 是否平滑处理
         * @return AnimationClip
         * @example getAnimationClipByName("Role1Action",{},ANIMATE_TYPE_BITMAP,false);
         */
        private static function getAnimationClipByName(name:String, info:Object, animateType:int = ANIMATE_TYPE_BITMAP, smoothing:Boolean = false):AnimationClip
        {
            var key:String = transformKey(name, info);
            if (animateType == ANIMATE_TYPE_BITMAP && _cacheDict.hasOwnProperty(key))
            {
                return new BitmapMovieClip(_cacheDict[key] as TextureGroup);
            }
            var mc:MovieClip = ResUtil.getNewObj(name);
            var ani:AnimationClip = McUtil.analyseMovieClipToAnimateClip(mc, info, animateType, smoothing);
            if (ani == null) return null;
            switch (animateType)
            {
                case ANIMATE_TYPE_MOVIE_CLIP:
                    return ani;
                case ANIMATE_TYPE_BITMAP:
                    _cacheDict[key] = (ani as BitmapMovieClip).getTexture();
                    _cacheGenerateQueue.push(key);
                    checkCacheQueue();
                    return ani;
                default:
                    return null;
            }
        }
        
        /**
         * 获取包含不同动作的BaseAnimation,用于人物、宠物、怪物动画（统一接口，没有特殊情况用这个）
         * @param name 资源名称
         * @param info 哪些部件需要替换
         * @return 将每个动作作为键值的Dictionary，每个键值对应一个Animation
         * @example getAnimation("Role1Action",{
         *     cloth:1,
         *     weapon:1,
         *     wing:1
         * });
         */
        public static function getAnimation(name:String, info:Object = null):BaseAnimation
        {
            if (!info)
            {
                info = {
                    cloth: 1,
                    weapon: 1,
                    wing: 1
                };
            }
            var ani:BaseAnimation = new BaseAnimation(new Dictionary());
            ani.sourceName = name;
            ani.replace = info;
            ani.animationType = SettingManager.getSettingVO().charAniType;
            return ani;
        }
        
        /**
         * 此API由BaseAnimation在获取新的动作时调用
         * 获取指定动作的AnimationClip
         */
        public static function getActionAnimation(name:String, info:Object, action:String, animateType:int = ANIMATE_TYPE_BITMAP, smoothing:Boolean = false):IAnimation
        {
            var key:String = transformKey(name, info, action);
            if (animateType == ANIMATE_TYPE_BITMAP && _cacheDict.hasOwnProperty(key))
            {
                return new BitmapMovieClip(_cacheDict[key] as TextureGroup);
            }
            var mc:MovieClip = ResUtil.getNewObj(name);
            var replacement:Object = {
                fashion_yf: info.cloth ? info.cloth : 1,
                fashion_wq: info.weapon ? info.weapon : 1,
                fashion_cb: info.wing ? info.wing : 1
            }
            var ani:IAnimation = McUtil.analyseMovieClipByAction(mc, replacement, action, animateType, smoothing);
            if (ani == null) return null;
            switch (animateType)
            {
                case ANIMATE_TYPE_MOVIE_CLIP:
                    return ani;
                case ANIMATE_TYPE_BITMAP:
                    _cacheDict[key] = (ani as BitmapMovieClip).getTexture();
                    _cacheGenerateQueue.push(key);
                    checkCacheQueue();
                    return ani;
                default:
                    return null;
            }
        }
        
        /**
         * 获取单独的、可渲染的动画（统一接口，没有特殊情况用这个）
         * @param name 资源名称
         * @param info 目前没有用处
         * @return AnimationClip
         */
        public static function getAnimationClip(name:String, info:Object = null):AnimationClip
        {
            if (!info)
            {
                info = {};
            }
            return getAnimationClipByName(name, info, SettingManager.getSettingVO().effAniType, false);
        }
        
        /**
         * 查看缓存序列，防止内存溢出
         */
        private static function checkCacheQueue():void
        {
            if (!_limitCacheSize) return;
            while (_cacheGenerateQueue.length > _cacheSizeLimit)
            {
                var key:String = _cacheGenerateQueue.shift();
                if (_cacheDict.hasOwnProperty(key))
                {
                    (_cacheDict[key] as TextureGroup).destroy();
                    delete _cacheDict[key];
                    Logger.log("清空BitmapMovieClip缓存: " + key);
                }
            }
        }
        
        public static function clearAllCache():void
        {
            UtilBase.getAllKeys(_cacheDict).forEach(function (key:String, a:*, b:*):void
            {
                if (_cacheDict[key] is TextureGroup)
                {
                    UtilBase.getAllValue(_cacheDict[key]).forEach(function (group:TextureGroup, a:*, b:*):void
                    {
                        group.destroy();
                    });
                }
                Logger.log("delete key: " + key)
                delete _cacheDict[key];
            });
            Logger.log("====== clear animation cache ======");
        }
    }
}
